﻿'******************************* File Header *********************************
'* File Name:    WmiConnection.vb
'* Project:      WmiConnection
'* Copyright (c) Freddy Kuehne
'*
'* Default implementation for a wmi connection.
'* 
'* This source is subject to the GNU Library General Public License (LGPL).
'* See http://wmiconnection.codeplex.com/license.
'* All other rights reserved.
'*****************************************************************************

' TODO: Log-Output
''' <summary>
''' Connects to a WMI (Windows Management Instrumentation).
''' </summary>
Public Class WmiConnection
  Inherits DbConnection
#Region "Variables"
  ''' <summary>
  ''' The WmiConnection uses an internal ConnectionStringBuilder to manage the connectionstring information.
  ''' </summary>
  Private m_ConStringBuilder As New WmiConnectionStringBuilder
#End Region

#Region "Constructors"
  ''' <summary>
  ''' Creates a new WmiConnection.
  ''' </summary>
  Public Sub New()
    Me.New(Nothing)
  End Sub

  ''' <summary>
  ''' Creates a new WmiConnection.
  ''' </summary>
  ''' <param name="connectionString">A connectionstring to be used for initialization</param>
  Public Sub New(ByVal connectionString As String)
    MyBase.New()
    Me.ConnectionString = connectionString
  End Sub
#End Region

#Region "Properties"
  ''' <summary>
  ''' Internal WMI-object.
  ''' </summary>
  Friend Property Wmi As ManagementObjectSearcher
#End Region

#Region "IDbConnection"
  ''' <summary>
  ''' <see cref="DbConnection.BeginDbTransaction"/>
  ''' </summary>
  ''' <exception cref="InvalidOperationException">Exception occurs, when the connection is not open</exception>
  Protected Overrides Function BeginDbTransaction(ByVal isolationLevel As IsolationLevel) As DbTransaction
    If (State <> ConnectionState.Open) Then Throw New InvalidOperationException
    BeginDbTransaction = New WmiTransaction(Me)
  End Function

  ''' <summary>
  ''' <see cref="DbConnection.ChangeDatabase"/>
  ''' </summary>
  ''' <exception cref="InvalidOperationException">Exception occurs, when the connection is not open</exception>
  ''' <exception cref="ArgumentNullException">Exception occurs, when an empty <paramref name="databaseName"/> is passed</exception>
  Public Overrides Sub ChangeDatabase(ByVal databaseName As String)
    If (State <> ConnectionState.Open) Then Throw New InvalidOperationException
    If (String.IsNullOrEmpty(databaseName)) Then Throw New ArgumentNullException("databaseName")
    Wmi.Scope.Path.NamespacePath = databaseName
  End Sub

  ''' <summary>
  ''' <see cref="DbConnection.Close"/>
  ''' </summary>
  Public Overrides Sub Close()
    If (Wmi IsNot Nothing) Then
      Wmi.Dispose()
      Wmi = Nothing
    End If
  End Sub

  ''' <summary>
  ''' <see cref="DbConnection.ConnectionString"/>
  ''' </summary>
  Public Overrides Property ConnectionString As String
    Get
      ConnectionString = m_ConStringBuilder.ConnectionString
    End Get
    Set(ByVal value As String)
      m_ConStringBuilder.ConnectionString = value
    End Set
  End Property

  ''' <summary>
  ''' <see cref="DbConnection.CreateDbCommand"/>
  ''' </summary>
  Protected Overrides Function CreateDbCommand() As DbCommand
    CreateDbCommand = New WmiCommand(Me)
  End Function

  ''' <summary>
  ''' <see cref="DbConnection.Database"/>
  ''' </summary>
  Public Overrides ReadOnly Property Database As String
    Get
      Database = Nothing
      If (Wmi IsNot Nothing) Then
        Database = Wmi.Scope.Path.NamespacePath
        If Not String.IsNullOrEmpty(Database) AndAlso Not Database.StartsWith("\", StringComparison.Ordinal) Then
          Database = "\" + Database
        End If
      End If
    End Get
  End Property

  ''' <summary>
  ''' <see cref="DbConnection.DataSource"/>
  ''' </summary>
  Public Overrides ReadOnly Property DataSource As String
    Get
      DataSource = m_ConStringBuilder.Server
    End Get
  End Property

  ''' <summary>
  ''' <see cref="DbConnection.ServerVersion"/>
  ''' </summary>
  ''' <remarks>
  ''' Returns the version number of windows.
  ''' </remarks>
  Public Overrides ReadOnly Property ServerVersion As String
    Get
      ServerVersion = String.Empty
      If (State = ConnectionState.Open) Then
        Using cmd As IDbCommand = CreateDbCommand()
          cmd.CommandText = "SELECT Version FROM Win32_OperatingSystem"
          ServerVersion = CStr(cmd.ExecuteScalar())
        End Using
      End If
    End Get
  End Property

  ''' <summary>
  ''' <see cref="DbConnection.Open"/>
  ''' </summary>
  Public Overrides Sub Open()
    Dim opt As ConnectionOptions = m_ConStringBuilder.Options
    If (State = ConnectionState.Open) Then Close()
    Wmi = New ManagementObjectSearcher(m_ConStringBuilder.Scope, String.Empty)
    If (opt IsNot Nothing) Then Wmi.Scope.Options = opt
    Wmi.Scope.Connect()
  End Sub

  ''' <summary>
  ''' <see cref="DbConnection.State"/>
  ''' </summary>
  Public Overrides ReadOnly Property State As ConnectionState
    Get
      If (Wmi Is Nothing) OrElse Not Wmi.Scope.IsConnected Then
        State = ConnectionState.Closed
      Else
        State = ConnectionState.Open
      End If
    End Get
  End Property
#End Region

#Region "IDisposable Support"
  Private disposedValue As Boolean ' So ermitteln Sie überflüssige Aufrufe

  ' IDisposable
  Protected Overrides Sub Dispose(ByVal disposing As Boolean)
    MyBase.Dispose(disposing)
    If Not Me.disposedValue Then
      If disposing Then
        ' Verwalteten Zustand löschen (verwaltete Objekte).
      End If

      ' Nicht verwaltete Ressourcen (nicht verwaltete Objekte) freigeben und Finalize() unten überschreiben.
      ' Große Felder auf NULL festlegen.
      Close()
    End If
    Me.disposedValue = True
  End Sub
#End Region
End Class
